<?php
/**
  * This is the core of the Elliot XML-RPC error reporting system for WordPress.
  * It is intended to provide plug-in authors with the unique ability to record
  * and act on custom errors thrown by their plug-ins.  Elliot will parse errors
  * as XML-RPC calls and report them back to a centrally-located database on the
  * plug-in author's server.  
  *
  * This is one-way communication only!
  *
  * For security purposes, Elliot will not accept any returned parameters on the
  * plug-in side of things.  The XML-RPC client will only recognize "success"
  * or "failure."
  *
  * You must define the location of the XML-RPC server when you instantiate your reporter.  Do
  * not modify anything in the Elliot package!
  *
  * Copyright 2010  Eric Mann  (email : eric@eamann.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, version 2, as 
  * published by the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
include_once(ABSPATH . WPINC . '/class-IXR.php');

if(!class_exists('JSBElliotClient') && version_compare(PHP_VERSION, '5.0', '>')) :
class JSBElliotClient {
	/* Define Variables */
	private static $uid;
	private static $wp_ver;
	private static $php_ver;
	private static $fopen;
	private static $server;
	private static $plugin;
	private static $version;
	
	private $client;
	
	public function __construct($serv, $plug, $ver) {
		$this->uid = substr(md5(get_bloginfo('url')),0,-12);
		$this->wp_ver = get_bloginfo('version');
		$this->php_ver = PHP_VERSION;
		$this->fopen = ini_get('allow_url_fopen');
		$this->server = $serv;
		$this->plugin = $plug;
		$this->version = $ver;				
		
		$this->client = new IXR_Client($this->server);
		
		// If more than one instance of Elliot is running
		if (!defined('ELLIOT_DO_ONCE')) {
			add_action(	'contextual_help', array($this, 'contextual_help') );
			add_action(	'admin_head', array($this, 'ask_permission_javascript'));
			define('ELLIOT_DO_ONCE', true);
		}

		// We haven't asked for permission yet, so do it now
		if ( !$this->check_permission() )
			add_action( 'admin_notices', array($this, 'message_ask_permission') );

		// Process our AJAX request
		add_action(	'wp_ajax_elliot_ask_permission', array($this, 'process_ask_permission') );
	}
	
	public function uid() {
		return $this->uid;
	}
	
	public function dispatch($message) {
	
		// Create a default array of information to send with each dispatch
		$defaults = Array(
			'uid'				=> $this->uid,
			'wp_version' 		=> $this->wp_ver,
			'php_version' 		=> $this->php_ver,
			'plugin_name' 		=> $this->plugin,
			'plugin_version'	=> $this->version,
			'fopen'				=> $this->fopen
		);
		
		$message = array_merge($defaults, $message);
			
		if(!$this->client->query('elliot.phoneHome', $message)) {
			$response = 'Something went wrong';
		} else {
			$response = $this->client->getResponse();
		}
		
		return $response;

	}
	
	public function check_permission($plugin = false) {

		// If they haven't provided a plugin name, default to current
		if (!$plugin)
			$plugin = $this->plugin;

		// Sanitize the plugin name
		$plugin_santitized = strtolower( $plugin );
		$plugin_santitized = str_ireplace( ' ', '_', $plugin_santitized );

		// Create an array of all Elliot permissions
		$elliot_permissions = Array();
		$elliot_permissions = get_option( 'Elliot_Permissions' );

		// Check the permissions of this plugin
		$plugin_permissions = $elliot_permissions[$plugin_santitized];

		// Permissions have been set, return it
		if ( !empty( $plugin_permissions ) )
			return $elliot_permissions[$plugin_santitized];

		// Permissions not set yet, return false
		else
			return false;

	}

	public function set_permission($plugin = false, $permission = false) {

		// If they haven't provided a plugin name, default to the current plugin
		if ($plugin == 'granted' || $plugin == 'denied') {
			$permission = $plugin;
			$plugin = $this->plugin;
		}

		// Sanitize the plugin name
		$plugin_santitized = strtolower($plugin);
		$plugin_santitized = str_ireplace(' ', '_', $plugin_santitized);

		// Create an array of all Elliot permissions from the DB record
		$elliot_permissions = Array();
		$elliot_permissions = get_option( 'Elliot_Permissions' );

		// Check the permission provided is valid
		if ( $permission == 'granted' || $permission == 'denied' ) {

			// Set the permission in the Array and update the DB
			$elliot_permissions[$plugin_santitized] = $permission;
			update_option( 'Elliot_Permissions', $elliot_permissions );

			return true;

		} else {

			return false;

		}

	}

	public function message_ask_permission() {

		// Sanitize the plugin name
		$plugin_santitized = strtolower($this->plugin);
		$plugin_santitized = str_ireplace(' ', '_', $plugin_santitized);

		echo '<div class="updated" style="text-align: center;">
		<form method="post" action="" class="elliot-permission" id="elliot_permission_for_'.$plugin_santitized.'">
		<input type="hidden" class="elliot_permission_for" name="elliot_permission_for" value="'.$this->plugin.'" />
		<p><strong>'.$this->plugin.'</strong> would like to send <strong>anonymous</strong> stats to the developer <strong>when errors occur</strong>, to improve the support you recieve.</p>
		<p><input type="submit" name="elliot_permission_granted" class="button-primary" value="Send Anonymous Stats" /> <input type="submit" class="button" name="elliot_permission_denied" value="No thanks." /></p>
		</form>
		</div>';

	}

	public function process_ask_permission() {

		// Grab the plugin name and sanitize it
		$plugin = $_POST['elliot_permission_for'];
		$plugin_santitized = strtolower($plugin);
		$plugin_santitized = str_ireplace(' ', '_', $plugin_santitized);

		// Grab what permission was set and sanitize it
		$permission = $_POST['elliot_permission'];
		$permission = str_ireplace('elliot_permission_', '', $permission);

		// Check the permission is valid, set the permission and output a message to the user
		if ( $permission == 'granted' ) {

			$this->set_permission( $plugin, 'granted' );
			echo '<p>Thank you, <strong>'.$plugin.'</strong> is now able to send anonymous error reports to the plugin developer if anything goes wrong. <a href="#" name="elliot_permission_denied">Undo</a></p>';

		} elseif ( $permission == 'denied' ) {

			$this->set_permission( $plugin, 'denied' );
			echo '<p>Okay, <strong>'.$plugin.'</strong> will not send any error reports to the plugin developer if things go wrong. <a href="#" name="elliot_permission_granted">Undo</a></p>';

		} else {

			echo 'Something went wrong.';

		}

		die();
	}

	public function ask_permission_javascript() {

		echo "<script type='text/javascript'>
			jQuery(document).ready(function() {
				
				jQuery('form.elliot-permission input[type=submit], form.elliot-permission a').live('click', function() {
		
					var parent = jQuery(this).parent().parent().attr('id');
					var data = {
						action: 'elliot_ask_permission',
						elliot_permission: jQuery(this).attr('name'),
						elliot_permission_for: jQuery('#'+parent+' .elliot_permission_for').val()
					};

					jQuery.post(ajaxurl, data, function(response) {
						jQuery('#'+parent+' p').remove();
						jQuery('#'+parent).append(response);
					});
					return false;

				});
			});
			</script>";
	}

	public function contextual_help($text) {
 		$text .= '<hr /><p><strong>Anonymous Error Reports</strong></p><p>One or more of your plugins can send anonymous error reports to the developer, if you have allowed it.</p><p>Because this data is anonymous and cannot be traced to you or your site, the plugin author may ask you to provide a <em>unique support code</em>. This code allows them to identify which reports were sent from your site, and then offer you specific advice based on that information.</p>
 		<p>Your unique support code is <strong>'.$this->uid.'</strong>.</p>';
		return $text;
	}	
}
endif;
?>